#define ZGRAPHICS_SOURCE
#include "Qt4Context.hpp"
#ifdef ZZZ_CONTEXT_QT4
#include <QtGui/QApplication>
#include "../Resource/Shader/ShaderSpecify.hpp"
#include "../Graphics/OpenGLTools.hpp"

namespace zzz{
//////////////////////////////////////////////////////////////////////////
//QTWidget
zQt4GLWidget::zQt4GLWidget(Renderer *renderer) {
  setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer));
  SetRenderer(renderer);
  setMouseTracking(true);
  setFocusPolicy(Qt::StrongFocus);
  setAutoBufferSwap(false);
  //glInit();
}


void zQt4GLWidget::initializeGL() {
#ifdef ZZZ_OPENGL_MX
  OpenGLMutex.Lock();
#endif // ZZZ_OPENGL_MX
  MakeCurrent();
  InitGLEW();
  renderer_->InitState();
  renderer_->InitData();
#ifdef ZZZ_OPENGL_MX
  OpenGLMutex.Unlock();
#endif // ZZZ_OPENGL_MX

  //init GraphicsGUI
  if (gui_) gui_->Init(renderer_);
}

void zQt4GLWidget::resizeGL(int width, int height) {
  Context::OnSize(0, width, height);
}

void zQt4GLWidget::paintGL() {
  RenderScene();
}

void zQt4GLWidget::mousePressEvent(QMouseEvent *event) {
  switch(event->button()) {
  case Qt::LeftButton:
    return Context::OnLButtonDown(GetInputFlag(),event->x(),event->y());
  case Qt::RightButton:
    return Context::OnRButtonDown(GetInputFlag(),event->x(),event->y());
  case Qt::MidButton:
    return Context::OnMButtonDown(GetInputFlag(),event->x(),event->y());
  }
}

void zQt4GLWidget::mouseReleaseEvent(QMouseEvent *event) {
  switch(event->button()) {
  case Qt::LeftButton:
    return Context::OnLButtonUp(GetInputFlag(),event->x(),event->y());
  case Qt::RightButton:
    return Context::OnRButtonUp(GetInputFlag(),event->x(),event->y());
  case Qt::MidButton:
    return Context::OnMButtonUp(GetInputFlag(),event->x(),event->y());
  }
}

void zQt4GLWidget::mouseMoveEvent(QMouseEvent *event) {
  return Context::OnMouseMove(GetInputFlag(),event->x(),event->y());
}

#ifndef QT_NO_WHEELEVENT
void zQt4GLWidget::wheelEvent(QWheelEvent *event) {
  return Context::OnMouseWheel(GetInputFlag(),event->delta()/120,event->x(),event->y());
}
#endif

void zQt4GLWidget::keyPressEvent(QKeyEvent *event) {
  unsigned int repeat=event->count();
  unsigned int c=0;
  if (!event->text().isEmpty())
    c=event->text()[repeat-1].toAscii();
  Context::OnKeyDown(QT4Key2ZZZKey(event->key()),repeat,GetInputFlag());
  if (c!=0) {
    Context::OnChar(c,repeat,GetInputFlag());
  }
}

void zQt4GLWidget::keyReleaseEvent(QKeyEvent *event) {
  unsigned int repeat=event->count();
  return Context::OnKeyUp(QT4Key2ZZZKey(event->key()),repeat,GetInputFlag());
}

unsigned int zQt4GLWidget::GetInputFlag() {
  unsigned int flag=0;
  Qt::KeyboardModifiers keystatus=QApplication::keyboardModifiers();
  if (CheckBit(keystatus,Qt::ShiftModifier)) SetBit(flag,ZZZFLAG_SHIFT);
  if (CheckBit(keystatus,Qt::ControlModifier)) SetBit(flag,ZZZFLAG_CTRL);
  if (CheckBit(keystatus,Qt::AltModifier)) SetBit(flag,ZZZFLAG_ALT);
  if (CheckBit(keystatus,Qt::MetaModifier)) SetBit(flag,ZZZFLAG_META);
  Qt::MouseButtons mousestatus=QApplication::mouseButtons();
  if (CheckBit(mousestatus,Qt::LeftButton)) SetBit(flag,ZZZFLAG_LMOUSE);
  if (CheckBit(mousestatus,Qt::RightButton)) SetBit(flag,ZZZFLAG_RMOUSE);
  if (CheckBit(mousestatus,Qt::MidButton)) SetBit(flag,ZZZFLAG_MMOUSE);
  if (CheckBit(mousestatus,Qt::XButton1)) SetBit(flag,ZZZFLAG_X1MOUSE);
  if (CheckBit(mousestatus,Qt::XButton2)) SetBit(flag,ZZZFLAG_X2MOUSE);
  CompleteZZZFlags(flag);
  return flag;
}

unsigned int zQt4GLWidget::QT4Key2ZZZKey(int key) {
  switch(key) {
  case Qt::Key_Escape: return ZZZKEY_ESCAPE;
  case Qt::Key_Tab: return ZZZKEY_TAB;
  case Qt::Key_Backspace: return ZZZKEY_BACK;
  case Qt::Key_Return: return ZZZKEY_RETURN;
  case Qt::Key_Enter: return ZZZKEY_ENTER;
  case Qt::Key_Insert: return ZZZKEY_INSERT;
  case Qt::Key_Delete: return ZZZKEY_DELETE;
  case Qt::Key_Pause: return ZZZKEY_PAUSE;
  case Qt::Key_Print: return ZZZKEY_PRINT;
  case Qt::Key_Home: return ZZZKEY_HOME;
  case Qt::Key_End: return ZZZKEY_END;
  case Qt::Key_Left: return ZZZKEY_LEFT;
  case Qt::Key_Up: return ZZZKEY_UP;
  case Qt::Key_Right: return ZZZKEY_RIGHT;
  case Qt::Key_Down: return ZZZKEY_DOWN;
  case Qt::Key_PageUp: return ZZZKEY_PAGEUP;
  case Qt::Key_PageDown: return ZZZKEY_PAGEDOWN;
  case Qt::Key_Shift: return ZZZKEY_SHIFT;
  case Qt::Key_Control: return ZZZKEY_CTRL;
  case Qt::Key_Meta: return ZZZKEY_META;
  case Qt::Key_Alt: return ZZZKEY_ALT;
  case Qt::Key_CapsLock: return ZZZKEY_CAPSLOCK;
  case Qt::Key_NumLock: return ZZZKEY_NUM_LOCK;
  case Qt::Key_ScrollLock: return ZZZKEY_ESCAPE;
  case Qt::Key_F1: return ZZZKEY_F1;
  case Qt::Key_F2: return ZZZKEY_F2;
  case Qt::Key_F3: return ZZZKEY_F3;
  case Qt::Key_F4: return ZZZKEY_F4;
  case Qt::Key_F5: return ZZZKEY_F5;
  case Qt::Key_F6: return ZZZKEY_F6;
  case Qt::Key_F7: return ZZZKEY_F7;
  case Qt::Key_F8: return ZZZKEY_F8;
  case Qt::Key_F9: return ZZZKEY_F9;
  case Qt::Key_F10: return ZZZKEY_F10;
  case Qt::Key_F11: return ZZZKEY_F11;
  case Qt::Key_F12: return ZZZKEY_F12;
  case Qt::Key_F13: return ZZZKEY_F13;
  case Qt::Key_F14: return ZZZKEY_F14;
  case Qt::Key_F15: return ZZZKEY_F15;
  case Qt::Key_Menu: return ZZZKEY_MENU;
  case Qt::Key_Space: return ZZZKEY_SPACE;
  case Qt::Key_QuoteDbl: return ZZZKEY_DQM;
  case Qt::Key_NumberSign: return ZZZKEY_MINUS;
  case Qt::Key_Dollar: return ZZZKEY_DOLLAR;
  case Qt::Key_Percent: return ZZZKEY_PERCENT;
  case Qt::Key_Ampersand: return ZZZKEY_AMPERSAND;
  case Qt::Key_Apostrophe: return ZZZKEY_SQM;
  case Qt::Key_ParenLeft: return ZZZKEY_LP;
  case Qt::Key_ParenRight: return ZZZKEY_RP;
  case Qt::Key_Asterisk: return ZZZKEY_ASTERISK;
  case Qt::Key_Plus: return ZZZKEY_PLUS;
  case Qt::Key_Comma: return ZZZKEY_COMMA;
  case Qt::Key_Minus: return ZZZKEY_MINUS;
  case Qt::Key_Period: return ZZZKEY_DOT;
  case Qt::Key_Slash: return ZZZKEY_SLASH;
  case Qt::Key_0: return ZZZKEY_0;
  case Qt::Key_1: return ZZZKEY_1;
  case Qt::Key_2: return ZZZKEY_2;
  case Qt::Key_3: return ZZZKEY_3;
  case Qt::Key_4: return ZZZKEY_4;
  case Qt::Key_5: return ZZZKEY_5;
  case Qt::Key_6: return ZZZKEY_6;
  case Qt::Key_7: return ZZZKEY_7;
  case Qt::Key_8: return ZZZKEY_8;
  case Qt::Key_9: return ZZZKEY_9;
  case Qt::Key_Colon: return ZZZKEY_COLON;
  case Qt::Key_Semicolon: return ZZZKEY_SCOLON;
  case Qt::Key_Less: return ZZZKEY_LT;
  case Qt::Key_Equal: return ZZZKEY_EQUAL;
  case Qt::Key_Greater: return ZZZKEY_GT;
  case Qt::Key_Question: return ZZZKEY_QM;
  case Qt::Key_At: return ZZZKEY_AT;
  case Qt::Key_A: return ZZZKEY_a;
  case Qt::Key_B: return ZZZKEY_b;
  case Qt::Key_C: return ZZZKEY_c;
  case Qt::Key_D: return ZZZKEY_d;
  case Qt::Key_E: return ZZZKEY_e;
  case Qt::Key_F: return ZZZKEY_f;
  case Qt::Key_G: return ZZZKEY_g;
  case Qt::Key_H: return ZZZKEY_h;
  case Qt::Key_I: return ZZZKEY_i;
  case Qt::Key_J: return ZZZKEY_j;
  case Qt::Key_K: return ZZZKEY_k;
  case Qt::Key_L: return ZZZKEY_l;
  case Qt::Key_M: return ZZZKEY_m;
  case Qt::Key_N: return ZZZKEY_n;
  case Qt::Key_O: return ZZZKEY_o;
  case Qt::Key_P: return ZZZKEY_p;
  case Qt::Key_Q: return ZZZKEY_q;
  case Qt::Key_R: return ZZZKEY_r;
  case Qt::Key_S: return ZZZKEY_s;
  case Qt::Key_T: return ZZZKEY_t;
  case Qt::Key_U: return ZZZKEY_u;
  case Qt::Key_V: return ZZZKEY_v;
  case Qt::Key_W: return ZZZKEY_w;
  case Qt::Key_X: return ZZZKEY_x;
  case Qt::Key_Y: return ZZZKEY_y;
  case Qt::Key_Z: return ZZZKEY_z;
  case Qt::Key_BracketLeft: return ZZZKEY_LSB;
  case Qt::Key_Backslash: return ZZZKEY_BSLASH;
  case Qt::Key_BracketRight: return ZZZKEY_RSB;
  case Qt::Key_Underscore: return ZZZKEY_UL;
  case Qt::Key_QuoteLeft: return ZZZKEY_BQ;
  case Qt::Key_BraceLeft: return ZZZKEY_LB;
  case Qt::Key_Bar: return ZZZKEY_VB;
  case Qt::Key_BraceRight: return ZZZKEY_RB;
  }
  return ZZZKEY_NOKEY;
}
}
#endif
